/*
 * soft_iic.c
 *
 *  Created on: 2023年12月31日
 *      Author: G
 */
#include <stdint.h>

#include "main.h"
#include "soft_iic.h"

// *********************************************** 模拟 I2c GPIO操作接口 **********************************************

// SCL 输出模式设置
static void Soft_IIC_SCL_Out_mode(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /*Configure GPIO pins : PAPin PAPin */
    GPIO_InitStruct.Pin = OLED_SCL_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(OLED_SCL_GPIO_Port, &GPIO_InitStruct);
}

// SCL 输出高电平
static void Soft_IIC_SCL_Set_High(void)
{
    HAL_GPIO_WritePin(OLED_SCL_GPIO_Port, OLED_SCL_Pin, GPIO_PIN_SET);
}

// SCL 输出低电平
static void Soft_IIC_SCL_Set_Low(void)
{
    HAL_GPIO_WritePin(OLED_SCL_GPIO_Port, OLED_SCL_Pin, GPIO_PIN_RESET);
}

// SDA 输出模式设置
static void Soft_IIC_SDA_Out_mode(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /*Configure GPIO pins : PAPin PAPin */
    GPIO_InitStruct.Pin = OLED_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(OLED_SDA_GPIO_Port, &GPIO_InitStruct);
}

// SDA 输出高电平
static void Soft_IIC_SDA_Set_High(void)
{
    HAL_GPIO_WritePin(OLED_SDA_GPIO_Port, OLED_SDA_Pin, GPIO_PIN_SET);
}

// SDA 输出低电平
static void Soft_IIC_SDA_Set_Low(void)
{
    HAL_GPIO_WritePin(OLED_SDA_GPIO_Port, OLED_SDA_Pin, GPIO_PIN_RESET);
}

// SDA 输入模式设置
static void Soft_IIC_SDA_In_mode(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /*Configure GPIO pins : PAPin PAPin */
    GPIO_InitStruct.Pin = OLED_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(OLED_SDA_GPIO_Port, &GPIO_InitStruct);
}

// SDA 返回输入状态
static int8_t Soft_IIC_SDA_Read_Sta(void)
{
    return HAL_GPIO_ReadPin(OLED_SDA_GPIO_Port, OLED_SDA_Pin);
}

// 微秒级延时
static void I2C_delay(void)
{
    delay_us(SOFT_IIC_SPEED);
}

// ********************************************************************************************************************

// 模拟IIC初始化
void soft_iic_Init(void)
{
    Soft_IIC_SCL_Out_mode();
    Soft_IIC_SDA_Out_mode();
    Soft_IIC_SCL_Set_High();
    Soft_IIC_SDA_Set_High();
}

// 产生IIC起始信号
static void I2C_Start(void)
{
    Soft_IIC_SDA_Out_mode();
    Soft_IIC_SDA_Set_High();
    Soft_IIC_SCL_Set_High();
    I2C_delay();
    Soft_IIC_SDA_Set_Low();
    I2C_delay();
    Soft_IIC_SCL_Set_Low();
}

// 产生IIC停止信号
static void I2C_Stop(void)
{

    Soft_IIC_SDA_Out_mode();
    Soft_IIC_SDA_Set_Low();
    Soft_IIC_SCL_Set_Low();
    I2C_delay();
    Soft_IIC_SCL_Set_High();
    I2C_delay();
    Soft_IIC_SDA_Set_High();
}

// 等待应答信号到来
// 返回值：1，接收应答失败
//         0，接收应答成功
static int8_t I2C_WaitAck(void)
{
    int8_t ack = 0;
    Soft_IIC_SDA_In_mode();
    Soft_IIC_SCL_Set_High();
    I2C_delay();

    ack = Soft_IIC_SDA_Read_Sta();

    Soft_IIC_SCL_Set_Low();
    return ack;
}

static void I2C_Ack(void)
{
    Soft_IIC_SDA_Out_mode();
    Soft_IIC_SDA_Set_Low();
    I2C_delay();
    Soft_IIC_SCL_Set_High();
    I2C_delay();
    Soft_IIC_SCL_Set_Low();
}

static void I2C_NoAck(void)
{
    Soft_IIC_SDA_Out_mode();
    Soft_IIC_SDA_Set_High();
    I2C_delay();
    Soft_IIC_SCL_Set_High();
    I2C_delay();
    Soft_IIC_SCL_Set_Low();
}

// IIC发送一个字节
// 返回从机有无应答
// 0，有应答
// -1，无应答
static int8_t I2C_SendByte(uint8_t SendByte) // 数据从高位到低位//
{
    uint8_t i = 8;
    Soft_IIC_SDA_Out_mode();

    while (i--)
    {
        if (SendByte & 0x80) {
            Soft_IIC_SDA_Set_High();
        }
        else {
            Soft_IIC_SDA_Set_Low();
        }
        SendByte <<= 1;
        Soft_IIC_SCL_Set_High();
        I2C_delay();
        Soft_IIC_SCL_Set_Low();
        I2C_delay();
    }
    return I2C_WaitAck();
}

// 读1个字节，ack=1时，发送ACK，ack=0，发送nACK
static int8_t I2C_ReadByte(uint8_t ack) // 数据从高位到低位//
{
    uint8_t i = 8;
    uint8_t ReceiveByte = 0;

    Soft_IIC_SDA_In_mode();
    while (i--)
    {
        Soft_IIC_SCL_Set_High();
        ReceiveByte <<= 1;
        I2C_delay();
        if (Soft_IIC_SDA_Read_Sta())
            ReceiveByte |= 0x01;
        Soft_IIC_SCL_Set_Low();
        I2C_delay();
    }

    if (ack)
        I2C_Ack(); // 发送nACK
    else
        I2C_NoAck(); // 发送ACK

    return ReceiveByte;
}

// 7bit地址多字节写入*****************************************
int8_t I2C_7bit_Mult_Write(uint8_t SlaveAddress, uint8_t *ptChar, uint8_t size)
{
    uint8_t i;

    if (size < 1)
        return SOFT_IIC_RESULT_SUCCESS;

    I2C_Start();
    if (I2C_SendByte(SlaveAddress << 1))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    for (i = 0; i < size; i++)
    {
        if (I2C_SendByte(*(ptChar + i)))
        {
            I2C_Stop();
            return SOFT_IIC_RESULT_ERROR;
        }
    }

    I2C_Stop();
    return SOFT_IIC_RESULT_SUCCESS;
}

// 7bit地址多字节读取*****************************************
int8_t I2C_7bit_Mult_Read(uint8_t SlaveAddress, uint8_t *ptChar, uint8_t size)
{
    uint8_t i;

    if (size < 1)
        return SOFT_IIC_RESULT_SUCCESS;

    I2C_Start();
    if (I2C_SendByte(SlaveAddress << 1 | 0X01))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    for (i = 1; i < size; i++)
        *ptChar++ = I2C_ReadByte(1);
    *ptChar++ = I2C_ReadByte(0);
    I2C_Stop();

    return SOFT_IIC_RESULT_SUCCESS;
}

// 10bit地址多字节写入*****************************************
int8_t I2C_10bit_Mult_Write(uint8_t SlaveAddress, uint8_t REG_Address, uint8_t *ptChar, uint8_t size)
{
    uint8_t i;

    if (size < 1)
        return SOFT_IIC_RESULT_SUCCESS;

    I2C_Start();
    if (I2C_SendByte(SlaveAddress << 1))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    if (I2C_SendByte(REG_Address))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    for (i = 0; i < size; i++)
    {
        if (I2C_SendByte(*(ptChar + i)))
        {
            I2C_Stop();
            return SOFT_IIC_RESULT_ERROR;
        }
    }

    I2C_Stop();
    return SOFT_IIC_RESULT_SUCCESS;
}

// 10bit地址多字节读取*****************************************
int8_t I2C_10bit_Mult_Read(uint8_t SlaveAddress, uint8_t REG_Address, uint8_t *ptChar, uint8_t size)
{
    uint8_t i;

    if (size < 1)
        return SOFT_IIC_RESULT_SUCCESS;

    I2C_Start();
    if (I2C_SendByte(SlaveAddress << 1))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    if (I2C_SendByte(REG_Address))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    I2C_Start();
    if (I2C_SendByte(SlaveAddress << 1 | 0X01))
    {
        I2C_Stop();
        return SOFT_IIC_RESULT_ERROR;
    }

    for (i = 1; i < size; i++)
        *ptChar++ = I2C_ReadByte(1);
    *ptChar++ = I2C_ReadByte(0);
    I2C_Stop();
    return SOFT_IIC_RESULT_SUCCESS;
}
